import copy
class BankAccount:
    # 类属性
    bank_name = "Python Bank"
    total_accounts = 0

    def __init__(self, account_holder, initial_balance=0, account_type="储蓄"):
        # 私有属性
        self.__account_number = self.__generate_account_number()
        self.__balance = initial_balance
        self.__transaction_history = []

        # 公有属性
        self.account_holder = account_holder
        self._account_type = account_type  # 使用保护属性，通过property控制

        # 更新类属性
        BankAccount.total_accounts += 1

        # 记录开户交易
        self.__transaction_history.append(f"开户 - 初始余额: ¥{initial_balance}")

    def __generate_account_number(self):
        """生成账户号（私有方法）"""
        import random
        return f"622202{random.randint(100000000, 999999999)}"

    # 私有方法
    def __validate_amount(self, amount):
        """验证金额是否合法（私有方法）"""
        if not isinstance(amount, (int, float)):
            raise ValueError("金额必须是数字")
        if amount <= 0:
            raise ValueError("金额必须大于0")
        return True

    def __record_transaction(self, transaction_type, amount, target=None):
        """记录交易历史（私有方法）"""
        import datetime
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        if target:
            record = f"{timestamp} - {transaction_type}: ¥{amount} -> {target.account_holder}"
        else:
            record = f"{timestamp} - {transaction_type}: ¥{amount}"
        self.__transaction_history.append(record)

    # 公有方法
    def deposit(self, amount):
        """存款"""
        self.__validate_amount(amount)
        self.__balance += amount
        self.__record_transaction("存款", amount)
        return self.__balance

    def withdraw(self, amount):
        """取款"""
        self.__validate_amount(amount)
        if amount > self.__balance:
            raise ValueError("余额不足")
        self.__balance -= amount
        self.__record_transaction("取款", amount)
        return self.__balance

    def transfer(self, target_account, amount):
        """转账到目标账户"""
        self.__validate_amount(amount)
        if not isinstance(target_account, BankAccount):
            raise ValueError("目标账户必须是BankAccount实例")
        if amount > self.__balance:
            raise ValueError("余额不足，无法转账")

        # 执行转账
        self.__balance -= amount
        target_account.__balance += amount  # 直接访问对方的私有属性（同类的实例可以访问）

        # 记录交易
        self.__record_transaction("转账支出", amount, target_account)
        target_account.__record_transaction("转账收入", amount, self)

        return self.__balance

    # 属性装饰器
    @property
    def balance(self):
        """余额只读属性"""
        return self.__balance

    @property
    def account_number(self):
        """账户号只读属性"""
        return self.__account_number

    @property
    def account_type(self):
        """账户类型属性"""
        return self._account_type

    @account_type.setter
    def account_type(self, value):
        """账户类型设置器，只能为'储蓄'或'信用卡'"""
        if value not in ["储蓄", "信用卡"]:
            raise ValueError("账户类型只能是'储蓄'或'信用卡'")
        self._account_type = value

    @property
    def transaction_count(self):
        """交易次数只读属性"""
        return len(self.__transaction_history)

    # 特殊方法
    def __str__(self):
        """用户友好显示"""
        return f"账户: {self.__account_number} | 持有人: {self.account_holder} | 类型: {self._account_type} | 余额: ¥{self.__balance:.2f}"

    def __repr__(self):
        """开发者显示，可用于重新创建对象"""
        return f"BankAccount('{self.account_holder}', {self.__balance}, '{self._account_type}')"

    def __eq__(self, other):
        """比较两个账户是否相同（按账户号）"""
        if not isinstance(other, BankAccount):
            return False
        return self.__account_number == other.__account_number

    def __len__(self):
        """返回交易记录数量"""
        return len(self.__transaction_history)

    # 类方法
    @classmethod
    def get_total_accounts(cls):
        """获取总账户数"""
        return cls.total_accounts

    @classmethod
    def change_bank_name(cls, new_name):
        """修改银行名称"""
        cls.bank_name = new_name

    # 静态方法
    @staticmethod
    def is_valid_account_holder(name):
        """验证账户持有人姓名是否合法"""
        if not isinstance(name, str) or len(name.strip()) < 2:
            return False
        # 简单的姓名验证：只包含中文、英文和空格
        import re
        return bool(re.match(r'^[\u4e00-\u9fa5a-zA-Z\s]+$', name.strip()))

    # 特殊属性访问示例
    def account_info(self):
        """显示账户的特殊属性信息"""
        print(f"=== 账户特殊属性信息 ===")
        print(f"类名: {self.__class__.__name__}")
        print(f"模块: {self.__class__.__module__}")
        print(f"基类: {self.__class__.__bases__}")
        print(f"MRO: {self.__class__.__mro__}")
        print(f"字典: {self.__dict__}")
        print(f"类字典: {list(self.__class__.__dict__.keys())}")

    # 其他业务方法
    def get_recent_transactions(self, count=5):
        """获取最近交易记录"""
        return self.__transaction_history[-count:] if self.__transaction_history else []

    def get_full_transaction_history(self):
        """获取完整交易记录（返回副本保护原始数据）"""
        return self.__transaction_history.copy()

    def get_account_summary(self):
        """获取账户摘要"""
        return {
            'account_number': self.__account_number,
            'account_holder': self.account_holder,
            'account_type': self._account_type,
            'balance': self.__balance,
            'transaction_count': self.transaction_count
        }


if __name__ == "__main__":
    # 创建账户
    account1 = BankAccount("张三", 1000, "储蓄")
    account2 = BankAccount("李四", 500, "信用卡")

    print("账户创建成功:")
    print(f"账户1: {account1}")
    print(f"账户2: {account2}")

    # 测试存款取款
    print("\n=== 测试存款取款 ===")
    account1.deposit(500)
    print(f"存款后账户1余额: ¥{account1.balance}")

    account1.withdraw(200)
    print(f"取款后账户1余额: ¥{account1.balance}")

    # 测试转账
    print("\n=== 测试转账 ===")
    account1.transfer(account2, 300)
    print(f"转账后账户1余额: ¥{account1.balance}")
    print(f"转账后账户2余额: ¥{account2.balance}")

    # 测试属性访问
    print("\n=== 测试属性访问 ===")
    print(f"账户1余额: {account1.balance}")  # 使用property
    print(f"账户2余额: {account2.balance}")
    print(f"账户1类型: {account1.account_type}")

    # 测试属性设置器
    account1.account_type = "信用卡"
    print(f"修改后账户1类型: {account1.account_type}")

    # 测试特殊方法
    print("\n=== 测试特殊方法 ===")
    print(account1)  # 调用 __str__
    print(repr(account1))  # 调用 __repr__

    # 测试相等性
    account1_copy = copy.copy(account1)
    print(f"账户1 == 账户2: {account1 == account2}")
    print(f"账户1 == 账户1_copy: {account1 == account1_copy}")

    # 测试私有属性访问（应该失败）
    print("\n=== 测试封装性 ===")
    try:
        print(account1.__balance)  # 应该报错
    except AttributeError as e:
        print(f"正确捕获错误: {e}")

    # 测试类方法
    print("\n=== 测试类方法 ===")
    print(f"总账户数: {BankAccount.get_total_accounts()}")

    # 测试静态方法
    print("\n=== 测试静态方法 ===")
    print(f"姓名'张三'是否合法: {BankAccount.is_valid_account_holder('张三')}")
    print(f"姓名'123'是否合法: {BankAccount.is_valid_account_holder('123')}")

    # 测试交易记录
    print("\n=== 测试交易记录 ===")
    print(f"账户1交易次数: {len(account1)}")  # 使用 __len__
    print("最近3笔交易:")
    for transaction in account1.get_recent_transactions(3):
        print(f"  - {transaction}")

